<template>
  <div class="Tinymce-wrapper">
    <Editor :id="id" v-model="content" tag-name="div" :disabled="disabled" :init="init" />
  </div>
</template>

<script lang="ts">
  export default { name: 'Tinymce' }
</script>

<script setup lang="ts">
  // tinymce默认hidden，不引入则不显示编辑器
  import tinymce from 'tinymce/tinymce'

  //引入tinymce编辑器
  import Editor from '@tinymce/tinymce-vue'

  import 'tinymce/themes/silver/theme' //编辑器主题，不引入则报错
  import 'tinymce/icons/default' //引入编辑器图标icon，不引入则不显示对应图标
  import 'tinymce/models/dom'

  // 更多插件参考：https://www.tiny.cloud/docs/plugins/
  import 'tinymce/plugins/image' // 插入上传图片插件
  import 'tinymce/plugins/importcss' //图片工具
  import 'tinymce/plugins/media' // 插入视频插件
  import 'tinymce/plugins/table' // 插入表格插件
  import 'tinymce/plugins/lists' // 列表插件
  import 'tinymce/plugins/charmap' // 特殊字符
  import 'tinymce/plugins/wordcount' // 字数统计插件
  import 'tinymce/plugins/codesample' // 插入代码
  import 'tinymce/plugins/code' // 查看源码
  import 'tinymce/plugins/fullscreen' //全屏
  import 'tinymce/plugins/link' //
  import 'tinymce/plugins/preview' // 预览
  import 'tinymce/plugins/template' //插入模板
  import 'tinymce/plugins/save' // 保存
  import 'tinymce/plugins/searchreplace' //查询替换
  import 'tinymce/plugins/pagebreak' //分页
  import 'tinymce/plugins/insertdatetime' //时间插入

  import { buildUUID } from '@/utils/uuid'
  import { isNotEmpty } from '@/utils/isUtils'

  interface Props {
    id?: string

    /**
     * 默认值
     */
    modelValue: string

    /**
     * 高度
     */
    height?: number

    /**
     * 禁用
     */
    disabled?: boolean

    /**
     * 插件
     */
    plugins?: string

    /**
     * 工具条
     */
    toolbar?: string
  }

  const props = withDefaults(defineProps<Props>(), {
    id: `tiny_${buildUUID()}`,
    modelValue: '',
    disabled: false,
    plugins: 'lists image media table wordcount save preview',
    toolbar:
      'formats undo redo paste print fontsizeselect fontselect template fullpage|wordcount ltr rtl visualchars visualblocks toc spellchecker searchreplace|save preview pagebreak nonbreaking|media image|outdent indent aligncenter alignleft alignright alignjustify lineheight  underline quicklink h2 h3 blockquote numlist bullist table removeformat forecolor backcolor bold italic  strikethrough hr charmap link insertdatetime|subscript superscript cut codesample code |anchor preview fullscreen|help',
    height: 500
  })

  // update: 需要双向绑定的属性名
  const emit = defineEmits(['update:modelValue'])

  const content = ref('')

  /**
   * 监听父组件传递的值
   * 只执行一次
   */
  const watchOne = watch(
    () => props.modelValue,
    (newVal: string) => {
      content.value = newVal
      watchOne()
    }
  )

  /**
   * 监听内容有变化，就更新内容，将值返回给父组件
   */
  watch(content, (newVal) => {
    watchOne()
    emit('update:modelValue', newVal)
  })

  //////////////////////////////////////////////////
  // 初始化
  //////////////////////////////////////////////////

  const init = reactive({
    textContent: content.value,
    height: props.height, //注：引入autoresize插件时，此属性失效
    placeholder: '在这里输入文字',

    plugins: props.plugins, //插件配置
    toolbar: props.toolbar, //工具栏配置，设为false则隐藏

    language_url: '/libs/tinymce/langs/zh-Hans.js', //引入语言包文件
    language: 'zh-Hans', //语言类型
    skin_url: '/libs/tinymce/skins/ui/oxide', //皮肤：浅色
    // skin_url: '/libs/tinymce/skins/ui/oxide-dark',//皮肤：暗色

    menubar: 'file edit insert view format table tools', //菜单栏配置，设为false则隐藏，不配置则默认显示全部菜单，也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
    menu: {
      // file: { title: '文件', items: 'newdocument' },
      // edit: { title: '编辑', items: 'undo redo | cut copy paste pastetext | selectall' },
      insert: { title: '插入', items: 'link image  |  hr' },
      view: { title: '查看', items: 'visualaid' }
      // format: {
      //   title: '格式',
      //   items:
      //     'bold italic underline strikethrough superscript subscript | formats | removeformat',
      // },
      // table: { title: '表格', items: 'inserttable tableprops deletetable | cell row column' },
      // tools: { title: '工具', items: 'spellchecker code' },
    },
    fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', //字体大小
    font_formats:
      '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;',

    branding: false, //tiny技术支持信息是否显示
    resize: false, //编辑器宽高是否可变，false-否,true-高可变，'both'-宽高均可，注意引号
    statusbar: true, //最下方的元素路径和字数统计那一栏是否显示
    elementpath: false, //元素路径是否显示

    content_style: 'img {max-width:100%;}', //直接自定义可编辑区域的css样式
    content_css: '/libs/tinymce/styles/tinyContent.css', //以css文件方式自定义可编辑区域的css样式，css文件需自己创建并引入

    // images_upload_url: '/demo/upimg.php',  //后端处理程序的url
    // images_upload_base_path: '/demo',  //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.php
    // 此处为图片上传处理函数，这个直接用了base64的图片形式上传图片，
    // 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
    images_upload_handler: (blobInfo, progress) =>
      new Promise((resolve, reject) => {
        const img = `data:${blobInfo.blob().type};base64,${blobInfo.base64()}`
        resolve(img)
      })
  })

  //////////////////////////////////////////////////
  // 函数
  //////////////////////////////////////////////////
  /**
   * 构建富文本
   */
  function build() {
    tinymce.init // 初始化
  }

  //////////////////////////////////////////////////
  // 生命周期
  //////////////////////////////////////////////////
  onMounted(() => {
    nextTick(() => {
      if (isNotEmpty(props.modelValue)) {
        content.value = props.modelValue
        watchOne()
      }

      build()
    })
  })

  //////////////////////////////////////////////////
  // 暴露出去，父组件才可以调用到
  //////////////////////////////////////////////////
  defineExpose({
    build
  })
</script>

<style scoped lang="scss">
  .Tinymce-wrapper {
    width: 100%;

    :deep(.tox-promotion) {
      display: none;
    }
  }
</style>
